package io.demo.message.serial;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.MessageFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Hessian2 serialization protocol
 *
 * @author lijinting01
 */
public class Hessian2SerializedObject<T> extends SerializedObject<T> {

  private static final Logger LOGGER = LoggerFactory.getLogger(Hessian2SerializedObject.class);

  Hessian2SerializedObject(T object) {
    super(object);
  }

  @Override
  protected void beforeSerialize() {
    // do nothing
  }

  @Override
  protected byte[] doSerialization(T object) {

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    Hessian2Output hessian2Output = new Hessian2Output(outputStream);
    try {
      hessian2Output.startMessage();
      hessian2Output.writeObject(object);
      hessian2Output.completeMessage();
      hessian2Output.flush();
      return outputStream.toByteArray();
    } catch (IOException e) {
      String message = MessageFormat.format("Error serializing object : {0}", object);
      throw new SerializationException(message, e);
    } finally {
      try {
        hessian2Output.close();
      } catch (IOException e) {
        LOGGER.error("Error cleaning up Hessian2 Output", e);
      }
    }
  }

  @Override
  public T reverse() {
    ByteArrayInputStream inputStream = new ByteArrayInputStream(getByteArray());
    Hessian2Input hessian2Input = new Hessian2Input(inputStream);
    try {
      hessian2Input.startMessage();
      @SuppressWarnings("unchecked")
      Class<T> cc = (Class<T>) getObjectClass();
      T value = cc.cast(hessian2Input.readObject(cc));
      hessian2Input.completeMessage();
      return value;
    } catch (IOException e) {
      String message = MessageFormat.format(
          "Error serializing object : {0}", getBase64String());
      throw new SerializationException(message, e);
    } finally {
      try {
        hessian2Input.close();
      } catch (IOException e) {
        LOGGER.error("Error cleaning up Hessian2 Input", e);
      }
    }
  }
}
